#include "FSCEF.h"
#ifdef ALICE_JS_CEF_PORT
#include "Runtime/Log/Logger.h"
#include "Runtime/Utils/FileSystem.h"
#include "Runtime/String/StringUtils.h"
#include <shlwapi.h>
namespace Alice{
    bool FS::Execute(const CefString& name,
        CefRefPtr<CefV8Value> object,
        const CefV8ValueList& arguments,
        CefRefPtr<CefV8Value>& retval,
        CefString& exception) {
        if (name == "SelectFolder") {
            if(arguments.size()==0){
                return false;
            }
            if (false == arguments[0]->IsString()) {
                return false;
            }
            CefString tipString = arguments[0]->GetStringValue();
            TCHAR tipStringT[256];
            memset(tipStringT, 0, sizeof(tipStringT));
            StringUtils::UTF8ToUnicode(tipString.ToString().c_str(), tipStringT);
            TCHAR selectedFolderPath[256];
            memset(selectedFolderPath, 0, sizeof(tipStringT));
            if (FileSystem::SelectFolder(tipStringT, selectedFolderPath)) {
                char utf8Path[256] = {0};
                memset(utf8Path, 0, 256);
                StringUtils::UnicodeToUTF8(selectedFolderPath, utf8Path);
                StringUtils::ToSTDPath(utf8Path);
                retval = CefV8Value::CreateString(CefString(utf8Path));
            }
            else {
                retval = CefV8Value::CreateString("Canceled");
            }
            return true;
        }
        else if (name == "CreateDir") {
            if (arguments.size() == 0) {
                return false;
            }
            if (false == arguments[0]->IsString()) {
                return false;
            }
            CefString dirPathString = arguments[0]->GetStringValue();
            TCHAR dirPathStringT[256];
            memset(dirPathStringT, 0, sizeof(dirPathStringT));
            StringUtils::UTF8ToUnicode(dirPathString.ToString().c_str(), dirPathStringT);
            char asciiDirPath[256] = { 0 };
            memset(asciiDirPath, 0, 256);
            StringUtils::UnicodeToASCII(dirPathStringT, asciiDirPath, 256);
            FileSystem::CreateDir(asciiDirPath);
            return true;
        }
        else if (name == "Load") {
            if (arguments.size() != 1 || !arguments[0]->IsString()) {
                return false;
            }
            CefString pathString = arguments[0]->GetStringValue();
            TCHAR pathStringT[256];
            memset(pathStringT, 0, sizeof(pathStringT));
            StringUtils::UTF8ToUnicode(pathString.ToString().c_str(), pathStringT);
            char asciiPath[256] = { 0 };
            memset(asciiPath, 0, 256);
            StringUtils::UnicodeToASCII(pathStringT, asciiPath, 256);
            Debug("try to load %s", asciiPath);
            Alice::Data data;
            if (Alice::FileSystem::LoadDataFromPath(asciiPath, data)) {
                retval = CefV8Value::CreateArrayBufferWithCopy(data.mData, data.mDataLen);
            }
            else {
                retval = CefV8Value::CreateNull();
            }
            return true;
        }
        else if (name == "Store") {
            if (arguments.size() != 2) {
                return false;
            }
            if (!arguments[0]->IsString()) {
                return false;
            }
            if (!arguments[1]->IsArrayBuffer()) {
                return false;
            }
            CefString pathString = arguments[0]->GetStringValue();
            TCHAR pathStringT[256];
            memset(pathStringT, 0, sizeof(pathStringT));
            StringUtils::UTF8ToUnicode(pathString.ToString().c_str(), pathStringT);
            char asciiPath[256] = { 0 };
            memset(asciiPath, 0, 256);
            StringUtils::UnicodeToASCII(pathStringT, asciiPath, 256);
            size_t dataSizeLen = arguments[1]->GetArrayBufferByteLength();
            unsigned char* data = (unsigned char*)arguments[1]->GetArrayBufferData();
            Debug("Store Action : [%s] [%u]bytes", asciiPath, dataSizeLen);
            retval = CefV8Value::CreateBool(Alice::FileSystem::SaveData(asciiPath, data, dataSizeLen));
            return true;
        }
        else if (name == "CWD") {
            TCHAR buffer[MAX_PATH] = { 0 };
            GetCurrentDirectory(MAX_PATH, buffer);
            char utf8Path[256] = { 0 };
            memset(utf8Path, 0, 256);
            StringUtils::UnicodeToUTF8(buffer, utf8Path);
            StringUtils::ToSTDPath(utf8Path);
            retval = CefV8Value::CreateString(utf8Path);
            return true;
        }
        else if (name == "APPInstallDir") {
            TCHAR buffer[MAX_PATH];
            GetModuleFileName(NULL, buffer, MAX_PATH);
            PathRemoveFileSpec(buffer);
            char utf8Path[256] = { 0 };
            memset(utf8Path, 0, 256);
            StringUtils::UnicodeToUTF8(buffer, utf8Path);
            StringUtils::ToSTDPath(utf8Path);
            retval = CefV8Value::CreateString(utf8Path);
            return true;
        }
        else if (name == "CD") {
            if (arguments.size() != 1 || !arguments[0]->IsString()) {
                return false;
            }
            CefString pathString = arguments[0]->GetStringValue();
            TCHAR pathStringT[256];
            memset(pathStringT, 0, sizeof(pathStringT));
            StringUtils::UTF8ToUnicode(pathString.ToString().c_str(), pathStringT);
            SetCurrentDirectory(pathStringT);
            TCHAR buffer[MAX_PATH] = { 0 };
            GetCurrentDirectory(MAX_PATH, buffer);
            char utf8Path[256] = { 0 };
            memset(utf8Path, 0, 256);
            StringUtils::UnicodeToUTF8(buffer, utf8Path);
            StringUtils::ToSTDPath(utf8Path);
            retval = CefV8Value::CreateString(utf8Path);
            return true;
        }
        else {
            Debug("unprocessed function call [%s]",name.ToString().c_str());
        }
	    return false;
    }
    void FS::Export(CefRefPtr<CefV8Value> inScope){
        CefRefPtr<CefV8Value> fs = CefV8Value::CreateObject(nullptr, nullptr);
        CefRefPtr<FS> fsHandler = new FS;
        fs->SetValue("SelectFolder", CefV8Value::CreateFunction("SelectFolder", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        fs->SetValue("CreateDir", CefV8Value::CreateFunction("CreateDir", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        fs->SetValue("CD", CefV8Value::CreateFunction("CD", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        fs->SetValue("CWD", CefV8Value::CreateFunction("CWD", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        fs->SetValue("APPInstallDir", CefV8Value::CreateFunction("APPInstallDir", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        fs->SetValue("Load", CefV8Value::CreateFunction("Load", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        fs->SetValue("Store", CefV8Value::CreateFunction("Store", fsHandler), V8_PROPERTY_ATTRIBUTE_READONLY);
        inScope->SetValue("FS", fs, V8_PROPERTY_ATTRIBUTE_READONLY);
    }
}
#endif